home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / X-MENu / X-MENu.cp < prev   
Text File  |  2000-06-23  |  6KB  |  309 lines

  1. /*
  2.  
  3.     X-MENu
  4.     
  5.     written by Jim Correia
  6.     MacHack 15
  7.     June, 2000
  8.     
  9.     correia@barebones.com
  10.  
  11. */
  12.  
  13. #include <Appearance.h>
  14.  
  15. #ifdef powerc
  16. #pragma options align=mac68k
  17. #endif
  18.  
  19. typedef struct
  20. {
  21.     short    last_offset;
  22.     short    last_right;
  23.     short    reserved;
  24.     
  25.     struct
  26.     {
  27.         MenuHandle menu;
  28.         short    menu_left;
  29.     } menus[1];
  30. } **menu_list;
  31.  
  32. #ifdef powerc
  33. #pragma options align=reset
  34. #endif
  35.  
  36. static UniversalProcPtr    orig_draw_menubar;
  37. static MBarHookUPP        orig_mbar_hook = nil;
  38. static Handle            icon_suite;
  39. static UniversalProcPtr    orig_menu_select = nil;
  40.  
  41. static UniversalProcPtr    mbar_hook = nil;
  42. static UniversalProcPtr    old_hook = nil;
  43.  
  44. ProcInfoType __procinfo =  kPascalStackBased;
  45.  
  46. static MenuHandle get_apple_menu(void)
  47. {
  48.     MenuHandle    apple_menu = nil;
  49.     
  50.     menu_list list = (menu_list)LMGetMenuList();
  51.         
  52.     if ((**list).last_offset != 0)
  53.         apple_menu = (**list).menus[0].menu;
  54.  
  55.     return apple_menu;
  56. }
  57.  
  58. static MenuHandle get_file_menu(void)
  59. {
  60.     MenuHandle    file_menu = nil;
  61.     
  62.     menu_list list = (menu_list)LMGetMenuList();
  63.         
  64.     if ((**list).last_offset >= 1)
  65.         file_menu = (**list).menus[1].menu;
  66.  
  67.     return file_menu;
  68. }
  69.  
  70. static UniversalProcPtr ApplyTrapPatch(short trap, UniversalProcPtr patchPtr)
  71. {
  72.     UniversalProcPtr trapPtr;
  73.     
  74.     if (patchPtr == nil)
  75.         return nil;
  76.  
  77.     trapPtr = NGetTrapAddress (trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  78.     NSetTrapAddress (patchPtr, trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  79.     return trapPtr;
  80. }
  81.  
  82. enum
  83. {    
  84.     DrawMenuBarUPPInfo = kPascalStackBased,
  85.  
  86.     MenuSelectUPPInfo = kPascalStackBased
  87.                      | RESULT_SIZE(SIZE_CODE(sizeof(long)))
  88.                      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Point)))
  89.  
  90. };
  91.  
  92. static    void    init_icon()
  93. {
  94.     OSErr    anErr = noErr;
  95.     
  96.     if ( ! icon_suite )
  97.         anErr = GetIconSuite(&icon_suite, -16386, svAllAvailableData);
  98. }
  99.  
  100. static void    PatchedDrawMenubar()
  101. {
  102.     OSErr        anErr = noErr;
  103.     GrafPtr        save_port;
  104.     CGrafPtr    wmgr_port;
  105.     
  106.     if ( orig_draw_menubar )
  107.         CALL_ZERO_PARAMETER_UPP( orig_draw_menubar, DrawMenuBarUPPInfo );
  108.         
  109.     GetPort(&save_port);
  110.     GetCWMgrPort(&wmgr_port);
  111.     SetPort((GrafPtr)wmgr_port);
  112.         
  113.     init_icon();    
  114.     
  115.     if ( icon_suite != nil )
  116.     {
  117.         short         height = LMGetMBarHeight();
  118.         short         width = 640;
  119.         Rect        r, erase_rect;
  120.         GDHandle    device = GetMainDevice();
  121.         
  122.         if ( height < 20 )
  123.             height = 20;
  124.         
  125.         width = ( (**device).gdRect.right - (**device).gdRect.left );
  126.     
  127.         r.left = width / 2 - 8;
  128.         r.right = r.left + 16;
  129.         
  130.         r.top = 2;
  131.         r.bottom = r.top + 16;
  132.         
  133.         erase_rect = r;
  134.         InsetRect(&erase_rect, -4, 0);
  135.         erase_rect.top = 0;
  136.         erase_rect.bottom = height;
  137.         
  138.         DrawThemeMenuTitle(&erase_rect, &erase_rect, kThemeMenuActive, 0L, nil, nil);
  139.         
  140.         anErr = PlotIconSuite(&r, atNone, ttNone, icon_suite);
  141.         
  142.         // now nuke the original apple menu
  143.         
  144.         erase_rect.left = 10;
  145.         erase_rect.right = 30;
  146.         DrawThemeMenuTitle(&erase_rect, &erase_rect, kThemeMenuActive, 0L, nil, nil);
  147.     }
  148.     else
  149.         Debugger();
  150.     
  151.     SetPort(save_port);
  152. }
  153.  
  154. static  SInt16    MyMBARHook(Rect *r)
  155. {
  156.     SInt16        result = 0;
  157.     
  158.     short         width = 640;
  159.     Rect        icon_rect;
  160.     GDHandle    device = GetMainDevice();
  161.     
  162.     width = ( (**device).gdRect.right - (**device).gdRect.left );
  163.  
  164.     icon_rect.left = width / 2 - 8;
  165.     icon_rect.right = icon_rect.left + 16;
  166.     
  167.     icon_rect.top = r->top;
  168.     icon_rect.bottom = icon_rect.top + 16;
  169.         
  170.     if ( SectRect(&icon_rect, r, &icon_rect) )
  171.     {
  172.         result = 1;
  173.     }
  174.     else if ( r->left <= 30 ) // we are the apple menu
  175.     {
  176.         result = 1;
  177.     }
  178.  
  179.     return result;
  180. }
  181.  
  182. static long MenuSelectPatch(Point pt)
  183. {
  184.     GrafPtr        save_port;
  185.     CGrafPtr    wmgr_port;
  186.     
  187.     long        result = -1;
  188.     short         height = LMGetMBarHeight();
  189.     short         width = 640;
  190.     Rect        icon_rect;
  191.     GDHandle    device = GetMainDevice();
  192.     MenuHandle    apple_menu = get_apple_menu();
  193.     MenuHandle    file_menu = get_file_menu();
  194.  
  195.     if ( height < 20 )
  196.         height = 20;
  197.  
  198.     width = ( (**device).gdRect.right - (**device).gdRect.left );
  199.  
  200.     icon_rect.left = width / 2 - 8;
  201.     icon_rect.right = icon_rect.left + 16;
  202.     
  203.     icon_rect.top = 0;
  204.     icon_rect.bottom = height;
  205.     
  206.     if ( PtInRect(pt, &icon_rect) )
  207.     {
  208.         short         width = 640;
  209.         Rect        r, erase_rect;
  210.         GDHandle    device = GetMainDevice();
  211.         
  212.         OSErr        anErr = noErr;
  213.         
  214.         width = ( (**device).gdRect.right - (**device).gdRect.left );
  215.     
  216.         r.left = width / 2 - 8;
  217.         r.right = r.left + 16;
  218.         
  219.         r.top = 2;
  220.         r.bottom = r.top + 16;
  221.         
  222.         erase_rect = r;
  223.         InsetRect(&erase_rect, -4, 0);
  224.         erase_rect.top = 0;
  225.         erase_rect.bottom = height;
  226.         
  227.         GetPort(&save_port);
  228.         GetCWMgrPort(&wmgr_port);
  229.         SetPort((GrafPtr)wmgr_port);
  230.  
  231.         DrawThemeMenuTitle(&erase_rect, &erase_rect, kThemeMenuSelected, 0L, nil, nil);
  232.         
  233.         init_icon();    
  234.  
  235.         if ( icon_suite )
  236.             anErr = PlotIconSuite(&r, atNone, ttNone, icon_suite);
  237.         else
  238.             Debugger();
  239.  
  240.         SetPort(save_port);
  241.  
  242.         if ( apple_menu && file_menu )
  243.         {
  244.             short    left = icon_rect.left + 8;
  245.             
  246.             DeleteMenu((**apple_menu).menuID);
  247.             InsertMenu(apple_menu, -1);
  248.  
  249.             CalcMenuSize(apple_menu);
  250.             
  251.             left -= ( (**apple_menu).menuWidth / 2 );
  252.  
  253.             result = PopUpMenuSelect(apple_menu, height, left, 0);
  254.             
  255.             DeleteMenu((**apple_menu).menuID);
  256.             InsertMenu(apple_menu, (**file_menu).menuID);
  257.         }
  258.     }
  259.     else if ( pt.h <= 40 ) // we are the apple menu
  260.     {
  261.         result = 0;
  262.     }
  263.  
  264.     if ( orig_menu_select && ( result == -1 ) )
  265.     {
  266.         UniversalProcPtr    old_hook = LMGetMBarHook();
  267.         UniversalProcPtr    mbar_hook = NewMBarHookProc(MyMBARHook);
  268.             
  269.         LMSetMBarHook(mbar_hook);
  270.  
  271.         result = CALL_ONE_PARAMETER_UPP( orig_menu_select, MenuSelectUPPInfo, pt);
  272.         
  273.         LMSetMBarHook(old_hook);
  274.         
  275.         DisposeRoutineDescriptor(mbar_hook);
  276.     }
  277.     
  278.     DrawMenuBar();
  279.  
  280.     return result;
  281. }
  282.  
  283. void main(void)
  284. {
  285.     Handle    initCode = nil;
  286.     THz        theZone;
  287.  
  288.     initCode = Get1Resource('INIT', 0);
  289.     if (initCode == nil)
  290.         goto failure;
  291.  
  292.     DetachResource(initCode);
  293.     if (ResError() != noErr) 
  294.         goto failure;
  295.     
  296.     theZone = GetZone();
  297.     SetZone(SystemZone());
  298.  
  299.     HLockHi(initCode);
  300.     HNoPurge(initCode);
  301.     
  302.     init_icon();
  303.  
  304.     orig_draw_menubar = ApplyTrapPatch( _DrawMenuBar, NewRoutineDescriptor((ProcPtr)(PatchedDrawMenubar), DrawMenuBarUPPInfo, GetCurrentArchitecture()) );
  305.     orig_menu_select = ApplyTrapPatch( _MenuSelect,  NewRoutineDescriptor((ProcPtr)(MenuSelectPatch), MenuSelectUPPInfo, GetCurrentArchitecture()) );
  306.  
  307.     failure:;
  308. }
  309.